<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <link rel="stylesheet" href="../../public/css/bootstrap.min.css" />
        <link rel="stylesheet" href="../..//public/css/theme.css" />
        <link rel="stylesheet" href="../../public/css/toast.css" />
        <script src="../../components/icon-svg.js"></script>
        <script src="../../components/reconnect.js"></script>
        <script src="../../public/js/vue/vue.global.prod.js"></script>
        <script src="../../components/lepton.js"></script>
        <style>
            #app {
                font-size: 13px;
            }
            .mapping-item {
                display: flex;
                justify-content: space-between;
                gap: 16px;
                margin: 4px 0px 8px 0px;
                align-items: center;
            }
            .text-btn {
                padding: 0;
                border: 0;
                outline: none;
                background: transparent;
                font: inherit;
            }
            .text-btn:hover {
                outline: none;
            }
            .delete-btn {
                padding: 3px;
                border-radius: 5px;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <div class="mapping-item" v-for="(port,index) in ports">
                <button class="text-btn">
                    <icon-svg :name="port.notConnected?'offline':'online'" size="22px"></icon-svg>
                </button>
                <input
                    class="form-control form-control-sm"
                    :class="{'input-error': port.hasErrorClient}"
                    type="number"
                    v-model.number="port.clientPort"
                    :disabled="!port.notConnected" />
                <button class="btn btn-sm text-nowrap" @click="toggleDirection(port)">
                    {{direction(port)}}
                </button>
                <input
                    class="form-control form-control-sm"
                    :class="{'input-error': port.hasErrorServer}"
                    v-model.number="port.serverPort"
                    :disabled="!port.notConnected" />
                <button class="btn btn-sm text-nowrap" @click="onToggle(port)">
                    {{toggleText(port)}}
                </button>
                <button class="text-btn delete-btn hover" @click="onRemove(port,index)">
                    <icon-svg name="remove" size="22px"></icon-svg>
                </button>
            </div>
            <Reconnect></Reconnect>
        </div>
        <script src="../../public/icons/remove-icon.js"></script>
        <script src="../../public/icons/offline-icon.js"></script>
        <script src="../../public/icons/online-icon.js"></script>
        <script>
            const { createApp, ref, onMounted } = Vue
            const app = createApp({
                data() {
                    return {
                        ports: [
                            {
                                clientPort: '',
                                serverPort: '',
                                isIn: false,
                                notConnected: true
                            }
                        ]
                    }
                },
                mounted() {
                    this.initChannel()
                },
                methods: {
                    async onInit() {
                        const response = await this.onFn('onInit')
                        this.ports = response
                    },
                    onButtonClick(name) {
                        switch (name) {
                            case '新建':
                                this.ports.push({
                                    clientPort: '',
                                    serverPort: '',
                                    isIn: false,
                                    notConnected: true
                                })
                                break
                        }
                    },
                    direction(item) {
                        if (item.isIn) {
                            return '入方向'
                        }
                        return '出方向'
                    },
                    toggleText(item) {
                        if (item.notConnected) {
                            return '启用'
                        }
                        return '停止'
                    },
                    async toggleDirection(item) {
                        if (!item.notConnected) {
                            await this.onFn('onDirectionChange', item)
                        }
                        item.isIn = !item.isIn
                    },
                    async onToggle(item) {
                        if (item.notConnected) {
                            return await this.onEnable(item)
                        }
                        await this.onDisable(item)
                    },
                    async onEnable(item) {
                        if (!this.validate(item)) {
                            return
                        }
                        try {
                            await this.onFn('onEnable', item)
                            item.notConnected = false
                        } catch (error) {
                            this.$toast.error(error.message)
                        }
                    },
                    async onDisable(item) {
                        await this.onFn('onDisable', item)
                        item.notConnected = true
                    },
                    async onRemove(item, index) {
                        if (!item.notConnected) {
                            await this.onFn('onRemove', item)
                        }
                        this.ports.splice(index, 1)
                    },
                    onPortForwardChanged(item) {
                        const port = this.ports.find(it => it.clientPort == item.clientPort)
                        if (port) {
                            port.notConnected = item.notConnected
                        }
                    },
                    validatePort(port) {
                        if (!/^[0-9]+$/.test(port)) {
                            throw new Error('端口号必须是小于等于 65535 的正整数')
                        }
                        const number = Number(port)
                        if (number > 65535) {
                            throw new Error('端口号必须是小于等于 65535 的正整数')
                        }
                        if (number < 1) {
                            throw new Error('端口号必须是小于等于 65535 的正整数')
                        }
                    },
                    validate(mapping) {
                        try {
                            this.validatePort(mapping.clientPort)
                            mapping.hasErrorClient = false
                        } catch (error) {
                            mapping.hasErrorClient = true
                            this.$toast.error(error.message)
                            return false
                        }
                        try {
                            this.validatePort(mapping.serverPort)
                            mapping.hasErrorServer = false
                        } catch (error) {
                            mapping.hasErrorServer = true
                            this.$toast.error(error.message)
                            return false
                        }
                        return true
                    }
                }
            })
            app.use(window.lepton)
            app.mount('#app')
        </script>
    </body>
</html>
